#include "PawnPromotionAction.hpp"
#include "CriticalException.hpp"

#include <cassert>

PawnPromotionAction::PawnPromotionAction(const Position& pos, Piece::Type ptype)
	:	Action(Chess::getInstance()->getChessboard()->getCell(pos)->getPiece()->getColor(), Action::PAWN_PROMOTION), pos(pos)
{
	piece_type = ptype;
	npiece = 0;
	promoted_pawn = Chess::getInstance()->getChessboard()->getCell(pos)->getPiece();
	
	assert(promoted_pawn != 0);
}


PawnPromotionAction::PawnPromotionAction(Piece* ppawn, Piece::Type type)
	: Action(ppawn->getColor(), Action::PAWN_PROMOTION), pos(ppawn->getCell()->getPosition())
{
	piece_type = type;
	npiece = 0;
	promoted_pawn = ppawn;
}

PawnPromotionAction::PawnPromotionAction(Chess::Color color, const Position& pos, Piece::Type ptype)
	:	Action(color, Action::PAWN_PROMOTION), pos(pos) 
{
	piece_type = ptype;
	npiece = 0;
	promoted_pawn = Chess::getInstance()->getChessboard()->getCell(pos)->getPiece();
	
	assert(promoted_pawn != 0);
}

PawnPromotionAction::~PawnPromotionAction()
{}


void PawnPromotionAction::execute()
{
	// when reexecuted from playActions, we must reload the promoted pawn
	promoted_pawn = Chess::getInstance()->getChessboard()->getCell(pos)->getPiece();
	
	if (promoted_pawn->getType() != Piece::PAWN)
		throw new CriticalException("PawnPromotionAction : execute : trying to execute a pawn promotion on a piece whose type is not pawn");	
	
	Piece* pb = 0;
	
	promoted_pawn = Chess::getInstance()->getChessboard()->getCell(pos)->getPiece();
	Chess::getInstance()->getChessboard()->getCell(pos)->capturePiece();
	
	switch (piece_type)
	{
		case Piece::PAWN:
			throw new CriticalException("PAWNPROMACTION : execute : trying to promote as a PAWN !");
			break;
			
		case Piece::ROOK:
			Chess::getInstance()->getPlayer(color).addPiece(pb = new Rook(color, pos));
			break;
			
		case Piece::KNIGHT:
			Chess::getInstance()->getPlayer(color).addPiece(pb = new Knight(color, pos));
			break;
			
		case Piece::BISHOP:
			Chess::getInstance()->getPlayer(color).addPiece(pb = new Bishop(color, pos));
			break;
			
		case Piece::QUEEN:
			Chess::getInstance()->getPlayer(color).addPiece(pb = new Queen(color, pos));
			break;
			
		case Piece::KING:
			throw new CriticalException("PAWNPROMACTION : execute : trying to promote as a KING !!! Cheating ?");
			break;
	};
	
	if (pb == 0)
		throw new CriticalException("PAWNPROMACTION : it's impossible to promote the pawn, no piece is available");
	
	npiece = pb;
}


Piece*		PawnPromotionAction::getPiece() const
{	return (npiece);		}


const Position& PawnPromotionAction::getPosition() const
{	return (pos);	}

Piece::Type 	PawnPromotionAction::getPieceType() const
{	return (piece_type);	}


Piece*			PawnPromotionAction::getPromotedPawn() const
{	return (promoted_pawn);		}

